home *** CD-ROM | disk | FTP | other *** search
/ Komputer for Alle 2004 #2 / K-CD-2-2004.ISO / OpenOffice Sv / f_0397 / python-core-2.2.2 / lib / test / test_gc.py < prev    next >
Encoding:
Python Source  |  2003-07-18  |  5.7 KB  |  250 lines

  1. from test_support import verify, verbose, TestFailed
  2. import sys
  3. import gc
  4.  
  5. def expect(actual, expected, name):
  6.     if actual != expected:
  7.         raise TestFailed, "test_%s: actual %d, expected %d" % (
  8.             name, actual, expected)
  9.  
  10. def expect_nonzero(actual, name):
  11.     if actual == 0:
  12.         raise TestFailed, "test_%s: unexpected zero" % name
  13.  
  14. def run_test(name, thunk):
  15.     if verbose:
  16.         print "testing %s..." % name,
  17.     thunk()
  18.     if verbose:
  19.         print "ok"
  20.  
  21. def test_list():
  22.     l = []
  23.     l.append(l)
  24.     gc.collect()
  25.     del l
  26.     expect(gc.collect(), 1, "list")
  27.  
  28. def test_dict():
  29.     d = {}
  30.     d[1] = d
  31.     gc.collect()
  32.     del d
  33.     expect(gc.collect(), 1, "dict")
  34.  
  35. def test_tuple():
  36.     # since tuples are immutable we close the loop with a list
  37.     l = []
  38.     t = (l,)
  39.     l.append(t)
  40.     gc.collect()
  41.     del t
  42.     del l
  43.     expect(gc.collect(), 2, "tuple")
  44.  
  45. def test_class():
  46.     class A:
  47.         pass
  48.     A.a = A
  49.     gc.collect()
  50.     del A
  51.     expect_nonzero(gc.collect(), "class")
  52.  
  53. def test_newstyleclass():
  54.     class A(object):
  55.         pass
  56.     gc.collect()
  57.     del A
  58.     expect_nonzero(gc.collect(), "staticclass")
  59.  
  60. def test_instance():
  61.     class A:
  62.         pass
  63.     a = A()
  64.     a.a = a
  65.     gc.collect()
  66.     del a
  67.     expect_nonzero(gc.collect(), "instance")
  68.  
  69. def test_newinstance():
  70.     class A(object):
  71.         pass
  72.     a = A()
  73.     a.a = a
  74.     gc.collect()
  75.     del a
  76.     expect_nonzero(gc.collect(), "newinstance")
  77.     class B(list):
  78.         pass
  79.     class C(B, A):
  80.         pass
  81.     a = C()
  82.     a.a = a
  83.     gc.collect()
  84.     del a
  85.     expect_nonzero(gc.collect(), "newinstance(2)")
  86.     del B, C
  87.     expect_nonzero(gc.collect(), "newinstance(3)")
  88.     A.a = A()
  89.     del A
  90.     expect_nonzero(gc.collect(), "newinstance(4)")
  91.     expect(gc.collect(), 0, "newinstance(5)")
  92.  
  93. def test_method():
  94.     # Tricky: self.__init__ is a bound method, it references the instance.
  95.     class A:
  96.         def __init__(self):
  97.             self.init = self.__init__
  98.     a = A()
  99.     gc.collect()
  100.     del a
  101.     expect_nonzero(gc.collect(), "method")
  102.  
  103. def test_finalizer():
  104.     # A() is uncollectable if it is part of a cycle, make sure it shows up
  105.     # in gc.garbage.
  106.     class A:
  107.         def __del__(self): pass
  108.     class B:
  109.         pass
  110.     a = A()
  111.     a.a = a
  112.     id_a = id(a)
  113.     b = B()
  114.     b.b = b
  115.     gc.collect()
  116.     del a
  117.     del b
  118.     expect_nonzero(gc.collect(), "finalizer")
  119.     for obj in gc.garbage:
  120.         if id(obj) == id_a:
  121.             del obj.a
  122.             break
  123.     else:
  124.         raise TestFailed, "didn't find obj in garbage (finalizer)"
  125.     gc.garbage.remove(obj)
  126.  
  127. def test_function():
  128.     # Tricky: f -> d -> f, code should call d.clear() after the exec to
  129.     # break the cycle.
  130.     d = {}
  131.     exec("def f(): pass\n") in d
  132.     gc.collect()
  133.     del d
  134.     expect(gc.collect(), 2, "function")
  135.  
  136. def test_frame():
  137.     def f():
  138.         frame = sys._getframe()
  139.     gc.collect()
  140.     f()
  141.     expect(gc.collect(), 1, "frame")
  142.  
  143.  
  144. def test_saveall():
  145.     # Verify that cyclic garbage like lists show up in gc.garbage if the
  146.     # SAVEALL option is enabled.
  147.     debug = gc.get_debug()
  148.     gc.set_debug(debug | gc.DEBUG_SAVEALL)
  149.     l = []
  150.     l.append(l)
  151.     id_l = id(l)
  152.     del l
  153.     gc.collect()
  154.     try:
  155.         for obj in gc.garbage:
  156.             if id(obj) == id_l:
  157.                 del obj[:]
  158.                 break
  159.         else:
  160.             raise TestFailed, "didn't find obj in garbage (saveall)"
  161.         gc.garbage.remove(obj)
  162.     finally:
  163.         gc.set_debug(debug)
  164.  
  165. def test_del():
  166.     # __del__ methods can trigger collection, make this to happen
  167.     thresholds = gc.get_threshold()
  168.     gc.enable()
  169.     gc.set_threshold(1)
  170.  
  171.     class A:
  172.         def __del__(self):
  173.             dir(self)
  174.     a = A()
  175.     del a
  176.  
  177.     gc.disable()
  178.     apply(gc.set_threshold, thresholds)
  179.  
  180. class Ouch:
  181.     n = 0
  182.     def __del__(self):
  183.         Ouch.n = Ouch.n + 1
  184.         if Ouch.n % 7 == 0:
  185.             gc.collect()
  186.  
  187. def test_trashcan():
  188.     # "trashcan" is a hack to prevent stack overflow when deallocating
  189.     # very deeply nested tuples etc.  It works in part by abusing the
  190.     # type pointer and refcount fields, and that can yield horrible
  191.     # problems when gc tries to traverse the structures.
  192.     # If this test fails (as it does in 2.0, 2.1 and 2.2), it will
  193.     # most likely die via segfault.
  194.  
  195.     gc.enable()
  196.     N = 200
  197.     for count in range(3):
  198.         t = []
  199.         for i in range(N):
  200.             t = [t, Ouch()]
  201.         u = []
  202.         for i in range(N):
  203.             u = [u, Ouch()]
  204.         v = {}
  205.         for i in range(N):
  206.             v = {1: v, 2: Ouch()}
  207.     gc.disable()
  208.  
  209. def test_all():
  210.     gc.collect() # Delete 2nd generation garbage
  211.     run_test("lists", test_list)
  212.     run_test("dicts", test_dict)
  213.     run_test("tuples", test_tuple)
  214.     run_test("classes", test_class)
  215.     run_test("new style classes", test_newstyleclass)
  216.     run_test("instances", test_instance)
  217.     run_test("new instances", test_newinstance)
  218.     run_test("methods", test_method)
  219.     run_test("functions", test_function)
  220.     run_test("frames", test_frame)
  221.     run_test("finalizers", test_finalizer)
  222.     run_test("__del__", test_del)
  223.     run_test("saveall", test_saveall)
  224.     run_test("trashcan", test_trashcan)
  225.  
  226. def test():
  227.     if verbose:
  228.         print "disabling automatic collection"
  229.     enabled = gc.isenabled()
  230.     gc.disable()
  231.     verify(not gc.isenabled() )
  232.     debug = gc.get_debug()
  233.     gc.set_debug(debug & ~gc.DEBUG_LEAK) # this test is supposed to leak
  234.  
  235.     try:
  236.         test_all()
  237.     finally:
  238.         gc.set_debug(debug)
  239.         # test gc.enable() even if GC is disabled by default
  240.         if verbose:
  241.             print "restoring automatic collection"
  242.         # make sure to always test gc.enable()
  243.         gc.enable()
  244.         verify(gc.isenabled())
  245.         if not enabled:
  246.             gc.disable()
  247.  
  248.  
  249. test()
  250.